-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Add support for limiting maximum execution time based on wall-time #6504
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
e519909
to
269509f
Compare
Not a fan of having two different max_execution_time settings that can both be active. I'd prefer the HHVM solution of toggling the meaning. I'd also be open to switching to wall-time only, which seems more useful to me, but I don't really get the technical reasons for the current choice... Maybe starting a discussion on internals will help understand why it works the way it does right now. |
Thanks for the feedback! Yeah, I'm ok with either way, I chose this solution for keeping BC completely intact, and because changing the meaning of an ini setting by another ini setting felt very controversial. In terms of the implementation, the other 2 solutions besides the current one are easier and cheaper (there is no double book keeping), so if I could choose, I'd also aim for counting the full wall-time. Unfortunately, neither can I imagine why the current solution was chosen back then. That said, I'll start a discussion soon, I just wanted to get some early feedback here, before announcing anything. :) |
269509f
to
d35dd7e
Compare
d35dd7e
to
0229684
Compare
@nikic has the mailing list discussion changed your point of view by chance (If you followed it)? My main fear about going the Hack way is that changing only one type of timeout on the fly would be cumbersome as you would have to set both ini settings at the same time, while by having the current implementation, it's ok if you only modify the ini setting you need. Also, I had difficulties with "aliasing" the two settings on Windows. Can you please have a technical review sometime soonish because I'd like to start the vote in the closer future. |
0229684
to
42646c0
Compare
@nikic I added two tests to document the interaction of the the new ini setting with the hard timeout, which was pointed out by you. Unfortunately the test which is supposed to be killed by reaching |
|
||
#ifndef ZTS | ||
if (EG(hard_timeout)) { | ||
zend_set_wall_timeout_ex(EG(hard_timeout), 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding https://externals.io/message/112492#112783, my understanding is that the following happens:
- when
max_execution_wall_time
is reached, the necessary globals are set (timed_out
andvm_interrupt
) - the timer is restarted with the
hard_timeout
when it has a value other than0
(BTW: shouldn't we disallow negative values?) - if the timeout is reached again, the process gets aborted
What is not clear for me, why timeouts inside internal functions can cause a process abort immediately, given their individual timeout is >= hard_timeout
? What am I missing?
Another thing I've just become unsure about is whether it is really a good idea to restart the real-time timer instead of the original CPU-time one:
zend_set_wall_timeout_ex(EG(hard_timeout), 1); | |
zend_set_timeout_ex(EG(hard_timeout), 1); |
ca22aad
to
a417436
Compare
a417436
to
2f948fa
Compare
Some functions has no timeout option (for ex. |
I wrote this initial code 25 years ago. At that time I couldn't use |
Thank you, @rlerdorf for this extensive background information, it was a fascinating read :) I'll try to gather more information about SAPIs with possible SIGALRM issues -- although I'm not sure it's a problem in practice since Windows (and a few more systems including IBM PASE) already only measures |
@kocsismate I think you mentioned that you're still interested in pursing this, right? 🙂 |
Yeah, definitely! I want to first finish a few other tasks (stubs, read only classes) and I try to finish it afterwards. P.s. i'd appreciate the constant stub review so that I can continue with the sensitive param change🙂 i'd like to avoid having to deal with conflicts |
#10141 introduces support for Currently, the patch uses CPU-based time to be consistent with existing behavior, but perhaps - as suggested by @morrisonlevi - should we take this opportunity to switch to wall time? In this case, compiling with #10141 also fixes the signal conflicts reported by @rlerdorf between PHP and other tools such as old-Apache, Go, and profilers. |
@kocsismate I'm not sure if I should review this. Please fix the merge conflicts first or close this or "convert to draft". |
@dstogov GitHub seems to have decided to flag a lot of people on old PRs |
Most likely, I'm not going to continue this RFC for the time being, so anyone can feel free to take it over. |
yeah. I got ~50 old PRs for review :( |
Now that #10141 has been merged and released, it's possible to opt-in for wall-time-based timers on Linux by setting the |
On most platforms, PHP currently measures timeouts based on the CPU time, rather than wall-time. This can be fairly surprising, since neither
sleep()
, nor network or system calls count towards the limit of themax_execution_time
config.Unfortunately, it is not only surprising, but it can have serious consequences for distributed systems with high traffic, where finishing a request in a timely manner is essential for avoiding cascading failures.
To make things even worse, there is no easy solution for the problem at all: e.g. when using PHP-FPM as process manager, one could define the
request_terminate_timeout
pool-level config option to stop execution after a certain amount of time at latest. This can help, but still falls short when there is a wide variety of acceptable timeout settings for the individual scripts. So in the end, one would have to maintain pools for slow and fast scripts... Clearly, this can be easily become a big burden.Of course, each individual network/system calls should have their own timeouts, however execution time can still easily go completely out of control when there are hundreds or even thousands of them during the same request. This also applies for CLI scripts (e.g. cron jobs) which can possibly execute millions of DB queries, although the
timeout
command comes in handy in this case. Another solution can be using something likeif (time() - $startTime > $timeout) { die("Timeout exceeded"); }
... But I don't even want to consider this idea.HHVM solved the problem by introducing the
TimeoutsUseWallTime
ini setting (facebook/hhvm@9a9b42e) in order to be able to change the meaning ofmax_execution_time
, while still (partially) remaining compatible with PHP.Contrarily to the above, I propose adding support for a
max_execution_wall_time
option, so that wall-time becomes measurable as well. A limitation of the implementation is that the timeout takes into effect on a best-effort basis, only after the network/system call which exceeded the time limit is finished. I do think this is an acceptable limitation, and still much better than having almost no control of the real execution time.